import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class PowerOutputMarkhovSpecific_deprecated {
	//state params to associate wind speeds
	private static double windStateSize = 5;
	private static int numWindStates = 10;

	//state params to associate power outputs
	private static int numPowerStates = 20;
	private static double powerStateSize = 15;

	//which state of wind should be considered
	private static int wind_state = 0;

	/**
	 * calculate which state a windspeed belongs to and return it
	 * @param windSpeed
	 * @return state association of a certain wind speed
	 */
	public static int getWindState(double windSpeed) {
		if (windSpeed / windStateSize > numWindStates) {
			System.err.println("Not Enough States: windSpeed:" + windSpeed + " Number of States: " + numWindStates
					+ " State Size: " + windStateSize);
			System.exit(-1);
		}
		return (int) (windSpeed / windStateSize);
	}

	/**
	 * 
	 * @param windState
	 * @return the lower bound of given wind state
	 */
	public static double getWindStateLowerBound(int windState) {
		return windState * windStateSize;
	}
	/**
	 * 
	 * @param windState
	 * @return the upper bound of given wind state
	 */
	public static double getWindStateUpperBound(int windState) {
		return (windState + 1) * windStateSize;
	}

	/**
	 * 
	 * @return all the possible list of wind states
	 */
	public static int[] getWindStates() {
		int[] temp = new int[numWindStates];
		for (int i = 0; i < numWindStates; i++) {
			temp[i] = i;
		}
		return temp;
	}

	/**
	 * Main driver of the program
	 * @param args
	 * @throws IOException
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws IOException, InterruptedException {
		// For a given state, ex:15-20mph
		// calculate markhov probabilities - probabilities of power states going into 15-20mph's power states
											//and probabilities of power states  going out of 15-20mph's power states

		//Initialize datapoint manager - holds datapoints and provides tools to work with datapoints
		DataPointManager_deprecated dpm = new DataPointManager_deprecated("harbec_data_output_row_april_may_2012.csv",
				"harbec_data_forecast_row_april_may2012.csv");
		//Get all the datapoints(hourly)
		TreeMap<Date, DataPoint> dpMap = dpm.getDataPoints();
		//Convert map to list so that previous values and next values can be naturally obtained instead of making a lookup call
		List<DataPoint> dpList = new ArrayList<DataPoint>(dpMap.values());

		//print out all the datapoints
		DecimalFormat df = new DecimalFormat("#.000");
		for (int d=0; d<dpList.size();d=d+8){//DataPoint dp : dpList) {
			DataPoint dp = dpList.get(d);
			System.out.println(dp.getId() + " " + dp.getForecastedDateTime() + " " + dp.getForecastDate() + " "
					+ dp.getWindSpeed()+ " "+df.format(dp.getAvgPowerOutput())+ " "+df.format(dp.getMedianPowerOutput()));
		}

		// Declare containers to hold markhov results
		TreeMap<String, TreeMap<String, Integer>> markhovMap = new TreeMap<String, TreeMap<String, Integer>>(
				new NumbersThenWordsComparator());
		// Initialize containers
		for (int i = 0; i < numPowerStates; i++) {
			markhovMap.put("S" + i, new TreeMap<String, Integer>(new NumbersThenWordsComparator()));
			for (int j = 0; j < numPowerStates; j++) {
				markhovMap.get("S" + i).put("S" + j, 0);
			}
		}
		double previousOutput = 0;
		double currentOutput = 0;
		boolean collectNext = false;
		for (DataPoint dp : dpList) {
			currentOutput = dp.getAvgPowerOutput();
			int current_output_belongs_to_state = (int) (currentOutput / powerStateSize);
			int previous_output_belongs_to_state = (int) (previousOutput / powerStateSize);

			// check if wind speed is in the correct state, otherwise dont do
			// next block. previousOutput lets us see the transition from previous state into current state
			// Use a boolean such that, if you current state is valid, you also read the next state to
			// to see the transitions from current state to the next state

			// if wind speed correct state or boolean collect next is true

			if (getWindState(dp.getWindSpeed()) == wind_state || collectNext == true) {
				// set collact next to false (default)
				collectNext = false;
				int current_state_transition_Count = markhovMap.get("S" + previous_output_belongs_to_state).get(
						"S" + current_output_belongs_to_state);
				int updated_current_state_transition_Count = current_state_transition_Count + 1;
				markhovMap.get("S" + previous_output_belongs_to_state).put("S" + current_output_belongs_to_state,
						updated_current_state_transition_Count);
				// if windspeed in the evaluation state, set collect next to true, to account transitions to next state
				if (getWindState(dp.getWindSpeed()) == wind_state) {
					collectNext = true;
				}
			}
			previousOutput = currentOutput;
		}
		System.out.println();
		System.out.println("Markhov Table for All Power state transitions in the Wind State " + wind_state + " ("
				+ getWindStateLowerBound(wind_state) + " - " + getWindStateUpperBound(wind_state) + "mph )");

		// Print column labels
		for (String colLabel : markhovMap.keySet()) {
			System.out.print("\t" + colLabel);
		}
		// print state values
		System.out.println();
		for (int i = 0; i < markhovMap.size(); i++) {
			System.out.print("\t" + /* i*state_size+ */"->" + ((i + 1) * powerStateSize));
		}
		// praint column labels
		System.out.println("\n");
		for (String colLabel : markhovMap.keySet()) {
			System.out.print("\t" + colLabel);
		}
		// print the data in the container
		System.out.println();
		for (String rowLabel : markhovMap.keySet()) {
			System.out.print(rowLabel + "\t");
			TreeMap<String, Integer> rowMap = markhovMap.get(rowLabel);
			for (String col : rowMap.keySet()) {
				System.out.print(rowMap.get(col) + "\t");
			}
			System.out.println();

		}
		System.out.println();
		// Print column labels
		for (String colLabel : markhovMap.keySet()) {
			System.out.print("\t" + colLabel);
		}
		System.out.println();
		// Calculate probabilities and print them
		//DecimalFormat df = new DecimalFormat("#.000");
		for (String row : markhovMap.keySet()) {
			System.out.print(row + "\t");
			TreeMap<String, Integer> rowMap = markhovMap.get(row);
			int rowSum = 0;
			for (int val : rowMap.values()) {
				rowSum = rowSum + val;
			}
			for (String col : rowMap.keySet()) {
				if (rowSum != 0) {
					System.out.print(df.format((rowMap.get(col) / ((double) rowSum))) + "\t");
				} else {
					System.out.print("x\t");
				}
			}
			System.out.println();

		}
		Thread.sleep(10000);
	}
}
